/*
 * Copyright (c) 2019. ascend 版权所有禁止转载。
 */

package cn.edu.zua.demo08.config;

import cn.edu.zua.demo08.module.test.entity.LogInfo;
import cn.edu.zua.demo08.module.test.mapper.LogInfoMapper;
import cn.edu.zua.demo08.util.LoggerUtils;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.time.Duration;
import java.time.LocalDateTime;

/**
 * 说明：
 *
 * @author ascend
 * 2019/1/24 13:55
 */
public class LogInterceptor implements HandlerInterceptor {
    private static final Logger log = LoggerFactory.getLogger(LogInterceptor.class);

    /**
     * log_entity
     */
    private static final String LOGGER_ENTITY = "_log_entity";

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //创建日志实体
        LogInfo logInfo = new LogInfo();
        logInfo.setLogClientIp(LoggerUtils.getClientIp(request));
        logInfo.setLogUri(request.getRequestURI());
        logInfo.setLogType(LoggerUtils.getRequestType(request));
        logInfo.setLogTypeMethod(request.getMethod());
        logInfo.setLogSessionId(request.getSession().getId());

        ObjectMapper om = new ObjectMapper();
        logInfo.setLogDataRequest(om.writeValueAsString(request.getParameterMap()));
        logInfo.setLogGmtRequest(LocalDateTime.now());
        //设置请求实体到request内，方面afterCompletion方法调用
        request.setAttribute(LOGGER_ENTITY, logInfo);

        return true;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        LogInfo logInfo = (LogInfo) request.getAttribute(LOGGER_ENTITY);
        logInfo.setLogDataResponse(new ObjectMapper().writeValueAsString(request.getAttribute(LoggerUtils.LOGGER_RETURN)));
        logInfo.setLogDataResponseStatusCode(response.getStatus());
        logInfo.setLogGmtResponse(LocalDateTime.now());
        logInfo.setLogGmtConsuming((int) Duration.between(logInfo.getLogGmtRequest(), LocalDateTime.now()).toMillis());

        log.debug("打印日志:{}", new ObjectMapper().writeValueAsString(logInfo));

        LogInfoMapper dao = getDAO(LogInfoMapper.class, request);
        dao.insert(logInfo);
    }

    /**
     * 根据传入的类型获取spring管理的对应dao
     *
     * @param clazz   类型
     * @param request 请求对象
     * @param <T> Class
     * @return Bean
     */
    private <T> T getDAO(Class<T> clazz, HttpServletRequest request) {
        BeanFactory factory = WebApplicationContextUtils.getRequiredWebApplicationContext(request.getServletContext());
        return factory.getBean(clazz);
    }
}
